from page.ui_arguments import Ui_Arguments
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import serial.tools.list_ports
from operation.logging import Logging
from serial_operation.serial_connect import SerialConnect
import os
import scipy.io as sio
import pandas as pd
import numpy as np
import threading
import time
from numpy import polyfit, poly1d


class Arguments(QWidget, Ui_Arguments):
    Signal_pwm = pyqtSignal(float, int, int)

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.serial_connect = SerialConnect()
        self.is_arduino_com_open = False
        self.is_pneumatic_com_open = False
        self.pushButton_pneumatic.toggled.connect(lambda: self.args_pushButton(1))
        self.pushButton_ardunio.toggled.connect(lambda: self.args_pushButton(0))
        self.pushButton_p.clicked.connect(self.pressure_send)
        self.pushButton_close.clicked.connect(self.pressure_close)
        self.pushButton_open.clicked.connect(self.open_calibration_file)
        self.pushButton_calibration.clicked.connect(self.calibration)
        self.calibration_thread = CalibrationThread()
        self.filename = ""

    def com_list(self):
        plist = tuple(serial.tools.list_ports.comports())
        if len(plist) <= 0:
            QMessageBox.about(self, '串口连接错误', '无串口可用')
            return False
        else:
            try:
                items = list()
                for i in range(len(plist)):
                    items.append(str(plist[i][0]))
                self.comboBox_pneumatic.clear()
                self.comboBox_ardunio.clear()
                self.comboBox_ardunio.addItems(items)
                self.comboBox_pneumatic.addItems(items)
            except Exception as e:
                Logging.logger.exception(e)
                return False

    def args_pushButton(self, i):
        if i == 0:
            port = self.comboBox_ardunio.currentText()
            if self.pushButton_ardunio.isChecked():
                if not self.serial_connect.connect_arduino_serial(port):
                    QMessageBox.about(self, 'Arduino串口链接异常', '串口连接失败')
                    self.pushButton_ardunio.setChecked(False)
                    self.pushButton_ardunio.setText('打开')
                    self.textEdit_serial_info.append('Arduino打开失败')
                    self.is_arduino_com_open = False
                else:
                    self.pushButton_ardunio.setText('关闭')
                    self.textEdit_serial_info.append('Arduino打开成功')
                    self.is_arduino_com_open = True
            else:
                self.serial_connect.serial_close(0)
                self.pushButton_ardunio.setText('打开')
                self.textEdit_serial_info.append('Arduino关闭')
                self.is_arduino_com_open = False
        elif i == 1:
            port = self.comboBox_pneumatic.currentText()
            if self.pushButton_pneumatic.isChecked():
                if not self.serial_connect.connect_pneumatic_serial(port):
                    QMessageBox.about(self, 'Pneumatic串口连接错误', '串口连接失败')
                    self.pushButton_pneumatic.setChecked(False)
                    self.pushButton_pneumatic.setText('打开')
                    self.textEdit_serial_info.append('Pneumatic打开失败')
                    self.is_pneumatic_com_open = False
                else:
                    self.pushButton_pneumatic.setText('关闭')
                    self.textEdit_serial_info.append('Pneumatic打开成功')
                    self.is_pneumatic_com_open = True
            else:
                self.serial_connect.serial_close(1)
                self.pushButton_pneumatic.setText('打开')
                self.textEdit_serial_info.append('Pneumatic关闭')
                self.is_pneumatic_com_open = False

    def pressure_send(self):
        if self.serial_connect.pneumatic_send(2):
            self.textEdit_serial_info.append('气泵0正压打开')
        if self.serial_connect.pneumatic_send(3):
            self.textEdit_serial_info.append('气泵1负压打开')

    def pressure_close(self):
        if self.serial_connect.pneumatic_send(0):
            self.textEdit_serial_info.append('气泵0关闭')
        if self.serial_connect.pneumatic_send(1):
            self.textEdit_serial_info.append('气泵1关闭')

    def open_calibration_file(self):
        cwd = os.getcwd() + "/test_data"
        file_name, file_type = QFileDialog.getOpenFileName(self, '选取标定文件', cwd, 'Csv Files (*.csv);;All Files (*)')
        if not file_name == "":
            self.lineEdit_address.setText(file_name)
            data = pd.read_csv(file_name, encoding='utf-8')
            self.p = list(data['P'])
            self.filename = file_name

    def calibration(self):
        count = int(self.lineEdit_count.text())
        p_thread = threading.Thread(target=self.calibration_thread.calibration, args=(self.p, count, self.filename),
                                    daemon=True)
        p_thread.start()


class CalibrationThread(QObject):
    Signal_p = pyqtSignal(float)
    Signal_p1 = pyqtSignal(int, int)

    def __init__(self):
        super().__init__()
        self.x = [0]
        self.y = [0]

    def calibration(self, pneumatic, count, filename):
        self.p = pneumatic
        self.x = np.zeros((count, len(self.p)))
        self.y = np.zeros((count, len(self.p)))
        for i in range(count):
            for k in range(len(self.p)):
                p = float(self.p[k])
                self.Signal_p.emit(p)
                time.sleep(2.5)
                self.Signal_p1.emit(i, k)
                time.sleep(0.5)

        x_1 = np.zeros(len(self.p))
        y_1 = np.zeros(len(self.p))
        for k in range(len(self.p)):
            for i in range(count):
                x_1[k] = x_1[k] + self.x[i][k]
                y_1[k] = y_1[k] + self.y[i][k]
            x_1[k] = round(x_1[k] / count)
            y_1[k] = round(y_1[k] / count)

        if not filename == "":
            data = pd.read_csv(filename, encoding='utf-8')
            localtime = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
            path = os.getcwd() + '\\test_data\\' + 'result ' + localtime + '.csv'
            data['x'] = x_1
            data['y'] = y_1
            data.to_csv(path, mode='a', index=False)
        p1 = np.zeros(220)
        x1 = np.zeros(220)
        y1 = np.zeros(220)
        for i in range(len(y_1)):
            y_1[i] = 400 - y_1[i]
        x = poly1d(polyfit(p1, x_1, 9))
        y = poly1d(polyfit(p1, y_1, 9))
        for i in range(220):
            p1[i] = -30 + i * 0.5
            y1[i] = y(p1[i])
            x1[i] = x(p1[i])

        sio.savemat('./XY.mat', {'p': p1, 'x': x1, 'y': y1})
